package app.gui;

import java.awt.BorderLayout;
import java.awt.Component;
import java.awt.FlowLayout;
import java.awt.Frame;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
import java.io.PrintWriter;
import java.text.ParseException;

import javax.swing.BorderFactory;
import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JDialog;
import javax.swing.JFormattedTextField;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.swing.text.MaskFormatter;

import app.Main;
import app.conn.WebDB;

/**
 * Dialog for edit greenhouse settings 
 * 
 * @author Lukas Vavra
 *
 */
public class SettingsDialog extends JDialog {

	private String unitId;

	private JCheckBox remoteSettings;
	private JTextField unitName;
	private JTextField token;
	private JTextField user;
	private JTextField mac;
	private JTextField ip;
	private JTextField mask;
	private JTextField dns;
	private JTextField gw;
	private JTextField servername;
	private JTextField serverip;

	private JPanel remotePanel;

	public SettingsDialog(Frame parent) {
		super(parent, "Výchozí konfigurace", true);
		JPanel panel = new JPanel(new GridBagLayout());
		GridBagConstraints cs = new GridBagConstraints();
		cs.insets = new Insets(10, 10, 10, 10);
		cs.fill = GridBagConstraints.HORIZONTAL;

		cs.gridx = 0;
		cs.gridy = 0;
		cs.weightx = 0;
		panel.add(new JLabel("Název zařízení: "), cs);

		unitName = new JTextField(20);
		cs.gridx = 1;
		cs.gridy = 0;
		cs.weightx = 1;
		panel.add(unitName, cs);

		remoteSettings = new JCheckBox("Vzdálená správa");
		cs.gridx = 0;
		cs.gridy = 1;
		cs.gridwidth = GridBagConstraints.REMAINDER;
		panel.add(remoteSettings, cs);

		remotePanel = new JPanel(new GridBagLayout());
		remotePanel.setBorder(BorderFactory.createTitledBorder("Síťové nastavení jednotky"));
		cs.gridx = 0;
		cs.gridy = 2;
		cs.gridwidth = GridBagConstraints.REMAINDER;
		panel.add(remotePanel, cs);


		cs.anchor = GridBagConstraints.WEST;
		cs.insets = new Insets(5, 5, 5, 5);

		cs.gridx = 0;
		cs.gridy = 0;
		cs.gridwidth = 1;
		cs.weightx = 0;
		remotePanel.add(new JLabel("32 znakový klíč: *"), cs);

		MaskFormatter formatter;
		try {
			formatter = new MaskFormatter("HHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHH");
			formatter.setPlaceholderCharacter(' ');
			token = new JFormattedTextField(formatter);
		} catch (ParseException e) {
			Main.showError("Systémová chyba", e.toString());
			System.exit(-1);
		}
		cs.gridx = 1;
		cs.gridy = 0;
		cs.weightx = 0;
		remotePanel.add(token, cs);

		cs.gridx = 0;
		cs.gridy = 1;
		cs.gridwidth = 1;
		cs.weightx = 0;
		remotePanel.add(new JLabel("Uživatelské jméno: *"), cs);

		user = new JTextField(20);
		cs.gridx = 1;
		cs.gridy = 1;
		cs.weightx = 0;
		remotePanel.add(user, cs);

		cs.gridx = 0;
		cs.gridy = 2;
		cs.gridwidth = 1;
		cs.weightx = 0;
		remotePanel.add(new JLabel("MAC adresa: *"), cs);

		try {
			formatter = new MaskFormatter("HH-HH-HH-HH-HH-HH");
			formatter.setPlaceholderCharacter(' ');
			mac = new JFormattedTextField(formatter);
		} catch (ParseException e) {
			Main.showError("Systémová chyba", e.toString());
			System.exit(-1);
		}
		cs.gridx = 1;
		cs.gridy = 2;
		cs.weightx = 0;
		remotePanel.add(mac, cs);


		cs.gridx = 0;
		cs.gridy = 3;
		cs.weightx = 0;
		remotePanel.add(new JLabel("IP adresa: "), cs);

		try {
			formatter = new MaskFormatter("***.***.***.***");
			formatter.setValidCharacters("0123456789 ");
			formatter.setPlaceholderCharacter(' ');
			ip = new JFormattedTextField(formatter);
		} catch (ParseException e) {
			Main.showError("Systémová chyba", e.toString());
			System.exit(-1);
		}
		cs.gridx = 1;
		cs.gridy = 3;
		cs.weightx = 1;
		remotePanel.add(ip, cs);

		cs.gridx = 0;
		cs.gridy = 4;
		cs.weightx = 0;
		remotePanel.add(new JLabel("Adresa DNS serveru: "), cs);

		try {
			formatter = new MaskFormatter("***.***.***.***");
			formatter.setValidCharacters("0123456789 ");
			formatter.setPlaceholderCharacter(' ');
			dns = new JFormattedTextField(formatter);
		} catch (ParseException e) {
			Main.showError("Systémová chyba", e.toString());
			System.exit(-1);
		}
		cs.gridx = 1;
		cs.gridy = 4;
		cs.weightx = 1;
		remotePanel.add(dns, cs);

		cs.gridx = 0;
		cs.gridy = 5;
		cs.weightx = 0;
		remotePanel.add(new JLabel("Brána: "), cs);

		try {
			formatter = new MaskFormatter("***.***.***.***");
			formatter.setValidCharacters("0123456789 ");
			formatter.setPlaceholderCharacter(' ');
			gw = new JFormattedTextField(formatter);
		} catch (ParseException e) {
			Main.showError("Systémová chyba", e.toString());
			System.exit(-1);
		}
		cs.gridx = 1;
		cs.gridy = 5;
		cs.weightx = 1;
		remotePanel.add(gw, cs);

		cs.gridx = 0;
		cs.gridy = 6;
		cs.weightx = 0;
		remotePanel.add(new JLabel("Maska podsítě: "), cs);

		try {
			formatter = new MaskFormatter("***.***.***.***");
			formatter.setValidCharacters("0123456789 ");
			formatter.setPlaceholderCharacter(' ');
			mask = new JFormattedTextField(formatter);
		} catch (ParseException e) {
			Main.showError("Systémová chyba", e.toString());
			System.exit(-1);
		}
		cs.gridx = 1;
		cs.gridy = 6;
		cs.weightx = 1;
		remotePanel.add(mask, cs);

		cs.gridx = 0;
		cs.gridy = 7;
		cs.weightx = 0;
		remotePanel.add(new JLabel("Adresa serveru: *"), cs);

		servername = new JTextField(20);
		cs.gridx = 1;
		cs.gridy = 7;
		cs.weightx = 1;
		remotePanel.add(servername, cs);

		cs.gridx = 0;
		cs.gridy = 8;
		cs.weightx = 0;
		remotePanel.add(new JLabel("IP adresa serveru: *"), cs);

		try {
			formatter = new MaskFormatter("***.***.***.***");
			formatter.setValidCharacters("0123456789 ");
			formatter.setPlaceholderCharacter(' ');
			serverip = new JFormattedTextField(formatter);
		} catch (ParseException e) {
			Main.showError("Systémová chyba", e.toString());
			System.exit(-1);
		}
		cs.gridx = 1;
		cs.gridy = 8;
		cs.weightx = 1;
		remotePanel.add(serverip, cs);

		cs.gridx = 1;
		cs.gridy = 9;
		cs.weightx = 0;
		remotePanel.add(new JLabel("*  Povinné údaje"), cs);

		remotePanel.setEnabled(false);
		for(Component c : remotePanel.getComponents()) {
			c.setEnabled(false);
		}


		JPanel buttonPanel = new JPanel(new FlowLayout(FlowLayout.TRAILING, 10, 10));
		JButton butOK = new JButton("Uložit");
		butOK.addActionListener(new ButOkListener());
		buttonPanel.add(butOK);

		JButton butCancel = new JButton("Storno");
		butCancel.addActionListener(new ButCancelListener());
		buttonPanel.add(butCancel);	

		add(panel, BorderLayout.CENTER);
		add(buttonPanel, BorderLayout.PAGE_END);

		loadSettings();

		remoteSettings.addItemListener(new ChkBoxListener());

		this.pack();
		this.setLocationRelativeTo(parent);
		this.setVisible(true);
	}

	private class ButOkListener implements ActionListener {

		@Override
		public void actionPerformed(ActionEvent arg0) {
			saveSettings();
			if(Main.isLogged())
				MainFrame.getInstance().getRemotePanel().refresh();
			dispose();
		}

	}

	private class ButCancelListener implements ActionListener {

		@Override
		public void actionPerformed(ActionEvent e) {
			if(unitId != null)
				try {
					WebDB.removeUnit(unitId);
				} catch (IOException e1) {
					Main.showError("Chyba připojení", "Nelze odebrat jednotku");				}
			dispose();
		}

	}

	private class ChkBoxListener implements ItemListener {

		@Override
		public void itemStateChanged(ItemEvent e) {			
			if(e.getStateChange() == ItemEvent.SELECTED) {
				if(!Main.isLogged()) {
					new LoginDialog(MainFrame.getInstance());
				}
				if(Main.isLogged()) {
					try {
						String[] result = WebDB.addUnit(unitName.getText());
						if(result.length > 2) {
							user.setText(Main.getUserName());
							token.setText(result[1]);
							unitId = result[2];
						}

						result = WebDB.getInfo();
						if(result.length > 2) {
							servername.setText(result[1]);
							serverip.setText(result[2]);
						}

					} catch (IOException e1) {
						Main.showError("Chyba připojení", "Nelze přidat novou jednotku");
						remoteSettings.setSelected(false);
						return;
					}

					remotePanel.setEnabled(true);
					for(Component c : remotePanel.getComponents()) {
						c.setEnabled(true);
					}
				}
				else {
					remoteSettings.setSelected(false);
				}
			}
			else {
				remotePanel.setEnabled(false);
				for(Component c : remotePanel.getComponents()) {
					c.setEnabled(false);
				}
				if(unitId != null)
					try {
						WebDB.removeUnit(unitId);
						unitId = null;
					} catch (IOException e1) {
						Main.showError("Chyba připojení", "Nelze odebrat jednotku");				
					}
			}
		}

	}

	private void loadSettings() {
		if(MainFrame.getInstance().setFile != null)
			try {
				BufferedReader reader = new BufferedReader(new FileReader(MainFrame.getInstance().setFile));
				/* first line -> unit name
				 * second line -> net mode 	0	1	2	3	4	5
				 * third line ->         		mac ip  dns gw  mask
				 * 								usr mac	ip	dns	gw
				 * 								key	usr	mac	ip	dns
				 * 								hip	key	usr	mac	ip
				 * 								had	hip	key	usr	mac
				 * 									had	hip	key	usr
				 * 										had	hip	key
				 * 											had	hip
				 * 												had	
				 */
				unitName.setText(reader.readLine());

				byte netmode = Byte.parseByte(reader.readLine());
				if(netmode > 0) {
					remoteSettings.setSelected(true);
					remotePanel.setEnabled(true);
					for(Component c : remotePanel.getComponents()) {
						c.setEnabled(true);
					}

					switch(netmode) {
					case 5 : 
						mask.setText(reader.readLine());
					case 4 :
						gw.setText(reader.readLine());
					case 3 :
						dns.setText(reader.readLine());
					case 2 :
						ip.setText(reader.readLine());
					}

					mac.setText(reader.readLine());
					user.setText(reader.readLine());
					token.setText(reader.readLine());
					serverip.setText(reader.readLine());
					servername.setText(reader.readLine());

					reader.close();
				}



			} catch (IOException e) {
				Main.showError("Chyba souboru", "Nelze otevřít soubor ".concat(MainFrame.SETFILE));
			} catch (NumberFormatException e2) {
				return;
			}
	}

	private void saveSettings() {
		if(MainFrame.getInstance().setFile != null)
			try {
				PrintWriter writer = new PrintWriter(MainFrame.getInstance().setFile);
				/* first line -> unit name
				 * second line -> net mode 	0	1	2	3	4	5
				 * third line ->         		mac ip  dns gw  mask
				 * 								usr mac	ip	dns	gw
				 * 								key	usr	mac	ip	dns
				 * 								hip	key	usr	mac	ip
				 * 								had	hip	key	usr	mac
				 * 									had	hip	key	usr
				 * 										had	hip	key
				 * 											had	hip
				 * 												had	
				 */

				byte netmode = 0;
				if(remoteSettings.isSelected())
					if(isValidMacAddress(mac.getText())) {
						netmode++;
						if(isValidAddress4(ip.getText())) {
							netmode++;
							if(isValidAddress4(dns.getText())) {
								netmode++;
								if(isValidAddress4(gw.getText())) {
									netmode++;
									if(isValidAddress4(mask.getText()))
										netmode++;						
								}
							}
						}
					}
					else {
						Main.showError("Chyba vstupu", "Chybný formát MAC adresy");
						remoteSettings.setSelected(false);
					}

				writer.println(unitName.getText());
				writer.println(netmode);

				if(netmode > 0) {
					switch(netmode) {
					case 5 : 
						writer.println(mask.getText());
					case 4 :
						writer.println(gw.getText());
					case 3 :
						writer.println(dns.getText());
					case 2 :
						writer.println(ip.getText());
					}

					writer.println(mac.getText());
					writer.println(user.getText());
					writer.println(token.getText());
					writer.println(serverip.getText());
					writer.println(servername.getText());
				}
				writer.close();
			} catch (IOException e) {
				Main.showError("Chyba souboru", "Nelze otevřít soubor ".concat(MainFrame.SETFILE));
				if(unitId != null)
					try {
						WebDB.removeUnit(unitId);
					} catch (IOException e1) {
						Main.showError("Chyba připojení", "Nelze odebrat jednotku");				
					}
				return;
			} catch (NumberFormatException e2) {
				return;
			}
	}

	private boolean isValidAddress4(String address) {
		String[] bytes = address.split("\\.");
		if(bytes.length != 4)
			return false;

		int b;
		for(int i = 0; i < 4; i++) {
			try {
				b = Integer.parseInt(bytes[i].trim());
				if(b > 255 || b < 0)
					return false;
			} catch(NumberFormatException e) {
				return false;
			}
		}
		return true;
	}

	private boolean isValidMacAddress(String address) {
		String[] bytes = address.split("-");
		if(bytes.length != 6)
			return false;

		int b;
		for(int i = 0; i < 6; i++) {
			try {
				b = Integer.parseInt(bytes[i].trim(), 16);
				if(b > 255 || b < 0)
					return false;
			} catch(NumberFormatException e) {
				return false;
			}
		}
		return true;
	}

}
